#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
#include <Arduino.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WiFi.h>

WiFiUDP ntpUDP; // 创建一个WIFI UDP连接
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60*60*8, 30*60*1000);

// Include the UI lib
#include "OLEDDisplayUi.h"

// Include custom images
#include "images.h"

// Initialize the OLED display using Wire library,SDA->21，SCL->22
SSD1306Wire  display(0x3c, 21, 22);

OLEDDisplayUi ui ( &display );

int count=0;
int menuIndex = 0;//二级菜单指示,1: 功能二级菜单 2：参数二级菜单 3：测量二级菜单 4: 语言二级菜单
int subMenuIndex = 0;//二级菜单下，使用上下按键操作时，选定的对象标志
int menuSwitch = 0;//0：一级菜单界面，1：二级菜单界面

#define KeyUp 34
#define KeyDown 35
#define LEFT 32
#define RIGHT 33
#define OK 25
#define BACK 26

int Function_Item=0;            //当前Bar项  范围:[0,ItemNum-1]  包括0 包括ItemNum-1  共包括ItemNum个取值
int Function_Item_Where=0;           //当前反显位置,[0,DispMax-1]  反映反显的Bar在屏幕上的位置
int Function_ItemNum = sizeof(Function_menuContent)/sizeof(Function_menuContent[0]);//计算内容数组的元素个数;         //Bar项数

int Parameter_Item=0;            //当前Bar项  范围:[0,ItemNum-1]  包括0 包括ItemNum-1  共包括ItemNum个取值
int Parameter_Item_Where=0;           //当前反显位置,[0,DispMax-1]  反映反显的Bar在屏幕上的位置
int Parameter_ItemNum = sizeof(Parameter_menuContent)/sizeof(Parameter_menuContent[0]);//计算内容数组的元素个数;         //Bar项数

int Language_Item=0;            //当前Bar项  范围:[0,ItemNum-1]  包括0 包括ItemNum-1  共包括ItemNum个取值
int Language_Item_Where=0;           //当前反显位置,[0,DispMax-1]  反映反显的Bar在屏幕上的位置
int Language_ItemNum = sizeof(Language_menuContent)/sizeof(Language_menuContent[0]);//计算内容数组的元素个数;         //Bar项数

int Mersure_Item=0;            //当前Bar项  范围:[0,ItemNum-1]  包括0 包括ItemNum-1  共包括ItemNum个取值
int Mersure_Item_Where=0;           //当前反显位置,[0,DispMax-1]  反映反显的Bar在屏幕上的位置
int Mersure_ItemNum = sizeof(Mersure_menuContent)/sizeof(Mersure_menuContent[0]);//计算内容数组的元素个数;         //Bar项数

int DispMax = 6;    //单屏可以显示的最大项 通常这是个固定值--因为你的液晶的大小决定了你一次可以显示的多少,你也可以在程序中修改,但记得维护它--因为所有的Bar型菜单都是要用到它的

//Bar型菜单初始化  公共部分
void BarMenuInit(int Item,int Where,String *arr,int ItemNum)
{
  display.clear();
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_10);
  if(ItemNum <= DispMax){ //总的条项小于或者等于液晶屏最大显示条项数
    for(int i=0;i<ItemNum;i++){
      display.drawString(10,i*10+1,arr[i]);
    }
    display.drawString(3,Where*10+1,"*");
    display.display();
  }
  else
  {
    if(Item >= DispMax-1){
      for(int i=0;i<DispMax;i++){
        display.drawString(10,i*10+1,arr[Item-5+i]);
      }
    }
    else{
      for(int i=0;i<ItemNum;i++){
        display.drawString(10,i*10+1,arr[i]);
      }
    }
    display.drawString(3,Where*10+1,"*");
    display.display();
  }
}

//Bar项菜单向上按键的行为
int BarMenuUp(int *Item,int *Where,int ItemNum)
{
  if(ItemNum <= DispMax){ //总的条项小于或者等于液晶屏最大显示条项数
    *Where-=1;
    if(*Where <= 0){
      *Where = 0;
    }
  }
  else
  {
    if(*Item<DispMax)
    {
      *Where-=1;
      if(*Where <= 0){ //超出显示范围
        *Where = 0;
      }
    }
    else
    {
      *Where=DispMax-1;
    }
    *Item-=1;
    if(*Item <= 0){
      *Item = 0;
    }
   
  }
}

//Bar项菜单向下按键的行为
int BarMenuDown(int *Item,int *Where,int ItemNum)
{
  if(ItemNum <= DispMax){ //总的条项小于或者等于液晶屏最大显示条项数
    *Where+=1;
    if(*Where >= ItemNum-1){
      *Where = ItemNum-1;
    }
  }
  else
  {
    *Where+=1;
    if(*Where >= DispMax-1){ //超出显示范围
      *Where = DispMax-1;
    }
    *Item+=1;
    if(*Item>=ItemNum-1){
      *Item=ItemNum-1;
    }
  }
}

void SmartConfig()
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig...");
  WiFi.beginSmartConfig();
  while (1)
  {
    Serial.print(".");
    delay(500);                   // wait for a second
    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      break;
    }
  }
}

bool AutoConfig()
{
    WiFi.begin();
    //如果觉得时间太长可改
    for (int i = 0; i < 20; i++)
    {
        int wstatus = WiFi.status();
        if (wstatus == WL_CONNECTED)
        {
          Serial.println("WIFI SmartConfig Success");
          Serial.printf("SSID:%s", WiFi.SSID().c_str());
          Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());
          Serial.print("LocalIP:");
          Serial.print(WiFi.localIP());
          Serial.print(" ,GateIP:");
          Serial.println(WiFi.gatewayIP());
          return true;
        }
        else
        {
          Serial.print("WIFI AutoConfig Waiting......");
          Serial.println(wstatus);
          delay(1000);
        }
    }
    Serial.println("WIFI AutoConfig Faild!" );
    return false;
}

void msOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
//  String shi_shiwei = timeClient.getFormattedTime().substring(0,8);
  String shijian = timeClient.getFormattedTime();
  int xinqi = timeClient.getDay();
  display->setTextAlignment(TEXT_ALIGN_RIGHT);
  display->setFont(ArialMT_Plain_10);
  display->drawString(128, 0, String(millis())+" "+shijian+" "+xinqi);
  count++;
  display->drawProgressBar(0,2,20,6,count);
  if(count == 100){
    count = 0;
  }
}

void function_logo_Frame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->drawXbm(x + 50, y + 14, function_logo_width, function_logo_height, function_logo);//
  menuIndex = 1;
}

void parameter_logo_Frame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->drawXbm(x + 50, y + 14, parameter_logo_width, parameter_logo_height, parameter_logo);//
  menuIndex = 2;
}

void measure_logo_Frame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->drawXbm(x + 50, y + 14, measure_logo_width, measure_logo_height, measure_logo);//
  menuIndex = 3;
}

void language_logo_Frame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->drawXbm(x + 50, y + 14, language_logo_width, language_logo_height, language_logo);//
  menuIndex = 4;
}

// This array keeps function pointers to all frames
// frames are the single views that slide in
FrameCallback frames[] = { function_logo_Frame, parameter_logo_Frame, measure_logo_Frame, language_logo_Frame };

// how many frames are there?
int frameCount = 4;

// Overlays are statically drawn on top of a frame eg. a clock
OverlayCallback overlays[] = { msOverlay };
int overlaysCount = 1;

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  pinMode(KeyUp,INPUT);
  pinMode(KeyDown,INPUT);
  pinMode(LEFT,INPUT);
  pinMode(RIGHT,INPUT);
  pinMode(OK,INPUT);
  pinMode(BACK,INPUT);

  ui.setTargetFPS(60);
  ui.setActiveSymbol(activeSymbol);
  ui.setInactiveSymbol(inactiveSymbol);
  ui.setIndicatorPosition(BOTTOM);
  ui.setIndicatorDirection(RIGHT_LEFT);
  // ui.setFrameAnimation(SLIDE_LEFT);
  ui.setFrames(frames, frameCount);
  ui.setOverlays(overlays, overlaysCount);
  
  ui.disableAutoTransition();
  ui.disableAllIndicators();
  ui.init();
  display.flipScreenVertically();
  display.setBrightness(100);
  // display.invertDisplay();
  // display.setFont(ArialMT_Plain_24);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  ui.setTimePerFrame(800);

  
 if (!AutoConfig())
 {
   SmartConfig();
 }
 while ( WiFi.status() != WL_CONNECTED ) {
   delay ( 500 );
   Serial.print ( "." );
 }
 timeClient.begin();
}

void loop() {
  //menuSwitch == 0,此时显示界面为动态菜单形式，图标加文字，使用左右按键进行滚动操作//
  if(menuSwitch == 0){
    int remainingTimeBudget = ui.update();
    if (remainingTimeBudget > 0) {
      timeClient.update();
      if(digitalRead(LEFT) == LOW){
        while(digitalRead(LEFT) == LOW){;}
        ui.setFrameAnimation(SLIDE_LEFT);
        ui.previousFrame();
        
      }
      if(digitalRead(RIGHT) == LOW){
        ui.setFrameAnimation(SLIDE_RIGHT);
        ui.nextFrame();
        while(digitalRead(RIGHT) == LOW){;}
      }
      if(digitalRead(OK) == LOW){
        menuSwitch = 1;
        while(digitalRead(OK) == LOW){;}
      }
      delay(remainingTimeBudget);
    }
  }
  //menuSwitch == 1,以下为进入二级菜单，根据menuIndex的值判断具体的二级菜单内容，此时启动上下按键对二级菜单实现滚动功能
  if(menuSwitch == 1){
    if(menuIndex == 1){  //1: 功能二级菜单
      BarMenuInit(Function_Item,Function_Item_Where,Function_menuContent,Function_ItemNum);
      if(digitalRead(KeyDown) == LOW){
        delay(50);
        while(digitalRead(KeyDown) == LOW);
        BarMenuDown(&Function_Item,&Function_Item_Where,Function_ItemNum);
      }
      if(digitalRead(KeyUp) == LOW){
        delay(50);
        while(digitalRead(KeyUp) == LOW);
       BarMenuUp(&Function_Item,&Function_Item_Where,Function_ItemNum);
      }
    }
    if(menuIndex == 2){  //2：参数二级菜单
      BarMenuInit(Parameter_Item,Parameter_Item_Where,Parameter_menuContent,Parameter_ItemNum);
      if(digitalRead(KeyDown) == LOW){
        delay(50);
        while(digitalRead(KeyDown) == LOW);
        BarMenuDown(&Parameter_Item,&Parameter_Item_Where,Parameter_ItemNum);
      }
      if(digitalRead(KeyUp) == LOW){
        delay(50);
        while(digitalRead(KeyUp) == LOW);
       BarMenuUp(&Parameter_Item,&Parameter_Item_Where,Parameter_ItemNum);
      }
    }
    if(menuIndex == 3){  //3：测量二级菜单
      BarMenuInit(Mersure_Item,Mersure_Item_Where,Mersure_menuContent,Mersure_ItemNum);
      if(digitalRead(KeyDown) == LOW){
        delay(50);
        while(digitalRead(KeyDown) == LOW);
        BarMenuDown(&Mersure_Item,&Mersure_Item_Where,Mersure_ItemNum);
      }
      if(digitalRead(KeyUp) == LOW){
        delay(50);
        while(digitalRead(KeyUp) == LOW);
       BarMenuUp(&Mersure_Item,&Mersure_Item_Where,Mersure_ItemNum);
      }
    }
    if(menuIndex == 4){  //4: 语言二级菜单
      BarMenuInit(Language_Item,Language_Item_Where,Language_menuContent,Language_ItemNum);
      if(digitalRead(KeyDown) == LOW){
        delay(50);
        while(digitalRead(KeyDown) == LOW);
        BarMenuDown(&Language_Item,&Language_Item_Where,Language_ItemNum);
      }
      if(digitalRead(KeyUp) == LOW){
        delay(50);
        while(digitalRead(KeyUp) == LOW);
       BarMenuUp(&Language_Item,&Language_Item_Where,Language_ItemNum);
      }
    }
    if(digitalRead(BACK) == LOW){
      menuSwitch = 0;
      while(digitalRead(BACK) == LOW){;}
    }
  }
}

